"""中间件"""
from scrapy import signals


class MidSpiderMiddleware:
    """爬虫中间件, 介于spider和引擎之间"""
    pass


class MidDownloaderMiddleware1:
    """下载器中间件1, 介于下载器和引擎之间"""

    @classmethod
    def from_crawler(cls, crawler):
        """设置 在什么时间，执行什么方法"""

        # 在爬虫启动时，执行 spider_opened方法
        s = cls()
        crawler.signals.connect(s.spider_opened, # 爬虫启动时
                                signal=signals.spider_opened) # 执行的方法
        return s

    def process_request(self, request, spider):
        """
        在引擎将请求的信息交给下载器之前, 自动的调用该方法
        :param request: 当前请求
        :param spider: 发出该请求的 spider
        :return:
            注意, process_request返回值是有规定的.
            1. 如果返回的None, 不做拦截. 继续向后面的中间件执行.
            2. 如果返回的是Request. 后续的中间件将不再执行.将请求重新交给引擎. 引擎重新扔给调度器
            3. 如果返回的是Response. 后续的中间件将不再执行.将响应信息交给引擎. 引擎将响应丢给spider. 进行数据处理
        """
        print("ware1, 我是process_requests")
        return None

    def process_response(self, request, response, spider):
        """
        在下载器返回响应准备交给引擎之间. 自动调用该方法
        :param request: 当前请求
        :param response:  响应内容
        :param spider: 发送请求的爬虫
        :return:
            1. request. 直接把请求交给引擎, 引擎将请求丢给调度器
            2. response. 不做拦截, 继续向前进行提交返回
        """
        print("ware1", "process_response")
        return response

    def process_exception(self, request, exception, spider):
        # 当前请求执行过程中, 出错了. 自动执行它
        pass

    def spider_opened(self, spider):
        """爬虫启动时，执行该方法 -- 只执行一次"""
        print("我是spider_opened")

class MidDownloaderMiddleware2:
    """下载器中间件2, 介于下载器和引擎之间"""
    def process_request(self, request, spider):
        """处理请求"""
        print("ware2, 我是process_requests")
        return None

    def process_response(self, request, response, spider):
        """处理响应"""
        print("我是ware2", "process_response")
        return response
